home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / PROG_TOO / C027B.ZIP / LIBFP / FP_PRT.C < prev    next >
Text File  |  1990-03-30  |  4KB  |  304 lines

  1.  
  2. #define MAXEC    40
  3.  
  4. static char *f_buf;
  5. static int f_upper;
  6.  
  7. static char ec_buf[MAXEC+10];
  8. static int ec_sign, ec_exp;
  9.  
  10. fp_print(x, fmtc, prec, ptmp)
  11. float x;
  12. char *ptmp;
  13. {
  14.     f_buf = ptmp;
  15.     f_upper = 0;
  16.  
  17.     switch (fmtc) {
  18.     case 'E':
  19.         f_upper = 1;
  20.     case 'e':
  21.         e_print(x, prec);
  22.         break;
  23.     case 'F':
  24.     case 'f':
  25.         f_print(x, prec);
  26.         break;
  27.     case 'G':
  28.         f_upper = 1;
  29.     case 'g':
  30.         g_print(x, prec);
  31.         break;
  32.     }
  33. }
  34.  
  35. static
  36. e_print(x, prec)
  37. float x;
  38. {
  39.     int nsig;
  40.     register char *p;
  41.  
  42.     if (prec < 0)
  43.         nsig = 7;
  44.     else
  45.         nsig = prec+1;
  46.  
  47.     ec_pr(x, nsig, 0);
  48.  
  49.     p = f_buf;
  50.     if (ec_sign)
  51.         *p++ = '-';
  52.     *p++ = ec_buf[0];
  53.     *p++ = '.';
  54.     if (nsig > 1)
  55.         strcpy(p, &ec_buf[1]);
  56.     p += strlen(p);
  57.     *p++ = f_upper ? 'E' : 'e';
  58.     ec_exp--;
  59.     if (ec_exp < 0) {
  60.         *p++ = '-';
  61.         ec_exp = -ec_exp;
  62.     }
  63.     if (ec_exp < 10)
  64.         *p++ = '0';
  65.     sprintf(p, "%d", ec_exp);
  66. }
  67.  
  68. static
  69. f_print(x, prec)
  70. float x;
  71. {
  72.     int nsig, nz, i;
  73.     register char *p;
  74.  
  75.     if (prec < 0)
  76.         nsig = 6;
  77.     else
  78.         nsig = prec;
  79.  
  80.     ec_pr(x, -nsig, 0);
  81.  
  82.     p = f_buf;
  83.     if (ec_sign)
  84.         *p++ = '-';
  85.     if (ec_exp < 1) {
  86.         *p++ = '0';
  87.     } else {
  88.         strncpy(p, ec_buf, ec_exp);
  89.         p += ec_exp;
  90.     }
  91.     if (prec != 0 || nsig)
  92.         *p++ = '.';
  93.     if (nsig == 0) {
  94.         *p = 0;
  95.         return;
  96.     }
  97.  
  98.     if (ec_exp < 0) {
  99.         nz = -ec_exp;
  100.         if (nz > nsig)
  101.             nz = nsig;
  102.         for (i=0; i<nz; i++)
  103.             *p++ = '0';
  104.         nsig -= nz;
  105.         if (nsig > 0) {
  106.             strncpy(p, ec_buf, nsig);
  107.             p += nsig;
  108.         }
  109.         *p = 0;
  110.     } else {
  111.         strcpy(p, &ec_buf[ec_exp]);
  112.     }
  113. }
  114.  
  115. static
  116. g_print(x, nsig)
  117. float x;
  118. {
  119.     int prec;
  120.  
  121.     if (nsig < 0)
  122.         nsig = 6;
  123.     if (nsig < 1)
  124.         nsig = 1;
  125.  
  126.     ec_pr(x, 1, 1);
  127.  
  128.     if (ec_exp < -3 || ec_exp > nsig)
  129.         e_print(x, nsig-1);
  130.     else {
  131.         prec = nsig - ec_exp;
  132.         f_print(x, prec);
  133.     }
  134. }
  135.  
  136. /*
  137.  * given x, ndig
  138.  *    if ndig is > 0, indicates number of significant digits
  139.  *    else -ndig is number of digits we want to the right of dec. pt.
  140.  * return the following:
  141.  *    appropriate number of digits of significance in ec_buf
  142.  *    ec_sign true if x was negative
  143.  *    ec_exp indicates the decimal point relative to leftmost digit
  144.  */
  145. static
  146. ec_pr(x, ndig, trunc)
  147. float x;
  148. {
  149.     int isneg;
  150.     int nhave;
  151.     long part;
  152.     int exp, newexp;
  153.     float rem;
  154.     char tbuf[20];
  155.  
  156.     /* ndig must be >= 1 and <= MAXEC */
  157.     if (x < 0.0) {
  158.         isneg = 1;
  159.         x = -x;
  160.     } else
  161.         isneg = 0;
  162.  
  163.     /* get some digits */
  164.     somedig(x, &part, &rem, &exp);
  165.  
  166.     sprintf(ec_buf, "%ld", part);
  167.     nhave = strlen(ec_buf);
  168.     exp = nhave + exp;
  169.  
  170.     if (ndig <= 0) {
  171.         ndig = -ndig;
  172.         ndig += exp;
  173.     }
  174.  
  175.     if (ndig < 1)
  176.         ndig = 1;
  177.     else if (ndig > MAXEC)
  178.         ndig = MAXEC;
  179.  
  180.     /* get some more digits */
  181.     while (nhave < ndig+1 && nhave < MAXEC) {
  182.         if (rem == 0.0) {
  183.             while (nhave < ndig+1)
  184.                 ec_buf[nhave++] = '0';
  185.             ec_buf[nhave] = 0;
  186.             break;
  187.         }
  188.  
  189.         x = rem;
  190.         somedig(x, &part, &rem, &newexp);
  191.  
  192.         sprintf(tbuf, "%ld", part);
  193.         newexp = strlen(tbuf) + newexp;
  194.         while (newexp++)
  195.             ec_buf[nhave++] = '0';
  196.         strcpy(&ec_buf[nhave], tbuf);
  197.         nhave = strlen(ec_buf);
  198.     }
  199.  
  200.     fround(ndig, trunc);
  201.     ec_sign = isneg;
  202.     ec_exp = exp;
  203. }
  204.  
  205. static
  206. fround(n, trunc)
  207. {
  208.     char *p;
  209.  
  210.     p = &ec_buf[n];
  211.     if (*p >= '5' && !trunc) {
  212.         p--;
  213.         while (p >= ec_buf) {
  214.             *p += 1;
  215.             if (*p < '9')
  216.                 goto done;
  217.             *p = '0';
  218.             p--;
  219.         }
  220.         ec_buf[0] = '1';
  221.     }
  222. done:
  223.     ec_buf[n] = 0;
  224. }
  225.  
  226. static
  227. somedig(x, lp, remp, expp)
  228. float x;
  229. long *lp;
  230. float *remp;
  231. int *expp;
  232. {
  233.     int bexp, dexp;
  234.     long ipart;
  235.     float rem;
  236.  
  237.     bexp = fgetexp(x);
  238.     dexp = 0;
  239.  
  240.     while (bexp > 31) {
  241.         x *= 1E-3;
  242.         dexp += 3;
  243.         bexp = fgetexp(x);
  244.     }
  245.     while (bexp < 10) {
  246.         x *= 1E3;
  247.         dexp -= 3;
  248.         if (dexp < -24) {
  249.             ipart = 0;
  250.             dexp = 0;
  251.             rem = 0.0;
  252.             goto iszero;
  253.         }
  254.         bexp = fgetexp(x);
  255.     }
  256.     fsplit(x, &ipart, &rem);
  257. iszero:
  258.     *lp = ipart;
  259.     *remp = rem;
  260.     *expp = dexp;
  261. }
  262.  
  263. static
  264. fgetexp(x)
  265. float x;
  266. {
  267.     char *p;
  268.     int i;
  269.  
  270.     p = (char *)&x;
  271.     i = p[3] & 0x7f;
  272.     i -= 0x40;
  273.     return i;
  274. }
  275.  
  276. static
  277. fsplit(x, vp, rp)
  278. float x, *rp;
  279. long *vp;
  280. {
  281.     long ival;
  282.     float rem;
  283.     int bexp, neg;
  284.  
  285.     ival = *(long *)&x;
  286.     neg = ival & 0x80;
  287.     ival &= ~0xff;
  288.  
  289.     bexp = fgetexp(x);
  290.  
  291.     if (bexp < 1) {
  292.         ival = 0;
  293.         rem = x;
  294.     } else {
  295.         ival = (unsigned long)ival >> (32-bexp);
  296.         if (neg)
  297.             ival = -ival;
  298.         rem = x - (float)ival;
  299.     }
  300.  
  301.     *vp = ival;
  302.     *rp = rem;    
  303. }
  304.